using System;
using System.IO;

namespace Dida
{
	/// <summary>
	/// A 3D sphere.
	/// </summary>
	public class Sphere
	{
		/// <summary>
		/// The center of the sphere.
		/// </summary>
		public Vector3D center;
		/// <summary>
		/// The radius of the sphere, measured from the center of the
		/// sphere, to it's surface.
		/// </summary>
		public float radius;

		/// <summary>
		/// Creates a sphere with it's center at 0,0,0 and a radius of 0.
		/// </summary>
		public Sphere() { }

		/// <summary>
		/// Creates a sphere from the given parameters.
		/// </summary>
		/// <param name="center">The initial center for the sphere.</param>
		/// <param name="radius">The initial radius for the sphere.</param>
		public Sphere(Vector3D center, float radius)
		{
			this.center = center;
			this.radius = radius;
		}

		/// <summary>
		/// Creates a sphere from the given parameters
		/// </summary>
		/// <param name="centerX">The initial x coordinate of the center of the sphere.</param>
		/// <param name="centerY">The initial y coordinate of the center of the sphere.</param>
		/// <param name="centerZ">The initial z coordinate of the center of the sphere.</param>
		/// <param name="radius">The initial radius of the sphare</param>
		public Sphere(float centerX, float centerY, float centerZ, float radius)
		{
			center = new Vector3D(centerX, centerY, centerZ);
			this.radius = radius;
		}

		/// <summary>
		/// Creates a clone of this object, ie. a new Sphere object that 
		/// matches this sphere.
		/// </summary>
		/// <returns>The new sphere.</returns>
		public Sphere Clone()
		{
			return new Sphere(center, radius);
		}

		/// <summary>
		/// Gets the bounding box of this sphere. The boundingbox is the smallest
		/// box that contains the whole sphere.
		/// </summary>
		/// <seealso cref="Box"/>
		public Box BoundingBox
		{
			get
			{
				Box ret = new Box();
				ret.min = center - new Vector3D(radius, radius, radius);
				ret.max = center + new Vector3D(radius, radius, radius);
				return ret;
			}
		}

		/// <summary>
		/// Returns whether the given sphere and this sphere intersects.
		/// </summary>
		/// <param name="b">The sphere that's tested against this sphere.</param>
		/// <returns>true when the spheres intersect, false otherwise</returns>
		public bool Intersects(Sphere b)
		{
			return IntersectionTests.SphereSphere(this, b);
		}

		/// <summary>
		/// Returns whether the given plane intersects this sphere.
		/// </summary>
		/// <param name="plane">The plane that's tested against this sphere.</param>
		/// <returns>true when the sphere and the plane intersect, false toherwise.</returns>
		public bool Intersects(Plane plane)
		{
			return IntersectionTests.PlaneSphere(plane, this);
		}

		/// <summary>
		/// Returns whether the given box intersects this sphere.
		/// </summary>
		/// <param name="box">The box that's tested against this sphere.</param>
		/// <returns>true when the sphere and the box intersect, false toherwise.</returns>
		public bool Intersects(Box box)
		{
			return IntersectionTests.SphereBox(this, box);
		}

		public void WriteBinary(BinaryWriter writer)
		{
			center.WriteBinary(writer);
			writer.Write(radius);
		}
	}
}